﻿/*
 *      	N3310LCD的MSP430FE425实现.
 *
 * 		作者：匿名
 *
 *		本软件为自由软件，你可以自由修改和发布.期望它能对你有所益处.
 *               
 *		最后修正时间：2008/7/20
 *		
 *		版权所有：中文中国
 */

#ifndef _LCD3310_
#define _LCD3310_
#include "io.h"
#include "time.h"
//#include "locale.h"
//#include "string.h"
#define COM 0		  	//写命令模式
#define DATA 1			//写数据模式

#define BASIC_MODE 0x20 	//基本功能设置 
#define EXPAND_MODE 0x21 	//扩展功能设置

#define HOR_ADDR 0x20		//水平寻址
#define VER_ADDR 0x22		//垂直寻址

#define BLANK_MODE 0x08		//白屏显示
#define REVERSE_MODE 0x0D	//反转显示
#define DISALL_MODE 0x09	//全显显示
#define NOMAL_MODE 0x0c		//正常显示

#define DOT_ARRAY_12 253         //12点阵字体
#define DOT_ARRAY_16 254         //16点阵字体
#define DOT_ARRAY_24 255         //18点阵字体
#define NULL 199
#define DOT_ARRAY_OTHER NULL    //其它点阵字体

typedef struct{
  const char name[2];
  const char fontmod[24];
}chinese;

#define moveto(xaddr,yaddr)  (lcd_setadd(xaddr,yaddr))
#define write_ch(p,xstarto,ystarto) (lcd_write_ch(p,xstarto, ystarto,DOT_ARRAY_6))

char xcurrent,ycurrent;
void lcd_write_ch(const char *p,char xstarto,char ystarto,int mod);

const char ASCII[][6] =
{
    /*{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },   // sp
    { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 },   // !
    { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 },   // "
    { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 },   // #
    { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 },   // $
    { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 },   // %
    { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 },   // &
    { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 },   // '
    { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 },   // (
    { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 },   // )
    { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 },   // *
    { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 },   // +
    { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 },   // ,
    { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 },   // -
    { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 },   // .
    { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 },   // /  */
    { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E },   // 0
    { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 },   // 1
    { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 },   // 2
    { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 },   // 3
    { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 },   // 4
    { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 },   // 5
    { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 },   // 6
    { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 },   // 7
    { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 },   // 8
    { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E },   // 9
   /* { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 },   // :
    { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 },   // ;
    { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 },   // <
    { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 },   // =
    { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 },   // >
    { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 },   // ?
    { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E },   // @
    { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C },   // A
    { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 },   // B
    { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 },   // C
    { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C },   // D
    { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 },   // E
    { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 },   // F
    { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A },   // G
    { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F },   // H
    { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 },   // I
    { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 },   // J
    { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 },   // K*/   
    { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F },   // M
    { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 },   // L
    { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 },   // .
    { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 },   // K
    { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 },   // C
    /*{ 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F },   // N
    { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E },   // O
    { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 },   // P
    { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E },   // Q
    { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 },   // R
    { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 },   // S
    { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 },   // T
    { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F },   // U
    { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F },   // V
    { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F },   // W
    { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 },   // X
    { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 },   // Y
    { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 },   // Z
    { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 },   // [
    { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 },   // 55
    { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 },   // ]
    { 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 },   // ^
    { 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 },   // _
    { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 },   // '
    { 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 },   // a
    { 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 },   // b
    { 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 },   // c
    { 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F },   // d
    { 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 },   // e
    { 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 },   // f
    { 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C },   // g
    { 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 },   // h
    { 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 },   // i
    { 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 },   // j
    { 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 },   // k
    { 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 },   // l
    { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 },   // m
    { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 },   // n
    { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 },   // o
    { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 },   // p
    { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC },   // q
    { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 },   // r
    { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 },   // s
    { 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 },   // t
    { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C },   // u
    { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C },   // v
    { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C },   // w
    { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 },   // x
    { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C },   // y
    { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 },   // z
    { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }    // horiz lines*/
};

	//写一字节 mod=0,命令模式 通用
void lcd_write_byte(char datatemp,char mod)
{ 
	char i=8;
	write_io(N3310,SCE,0); 
        if(mod)
	  write_io(N3310,DC,1);
        else
          write_io(N3310,DC,0);
	while (i--) { 
		if (datatemp&0x80){
			write_io(N3310,SDIN,1);
		} 
		else {
			write_io(N3310,SDIN,0);
		} 
		write_io(N3310,SCLK,0); 
		write_io(N3310,SCLK,1); 
		datatemp<<=1; 
	} 
	write_io(N3310,DC,1); 
	write_io(N3310,SCE,1); 
	write_io(N3310,SDIN,1); 
} 

	//初始化 通用
void lcd_init(void)  
{ 
	write_io(N3310,RES,0);
 	delay(10); 
	write_io(N3310,RES,1); 
	write_io(N3310,SCE,1); 
	write_io(N3310,SDIN,1); 
	write_io(N3310,SCLK,1); 
	lcd_write_byte(0x21,COM);		//初始化Lcd,功能设定使用扩充指令
 	lcd_write_byte(0xd5,COM);		//设定液晶偏置电压(高--低） 
	lcd_write_byte(0x20,COM);		//使用基本指令 
	lcd_write_byte(0x0C,COM);		//设定显示模式，正常显示 
       
} 

	//设定地址
void lcd_setadd(char xaddr,char yaddr) 
{ 	
		//设定x坐标,(a%83)使X轴坐标标定在83以内,有更好的健壮性;
        if(xaddr!=NULL)
	 lcd_write_byte(((xaddr%84)|0x80),0);
        else
          lcd_write_byte(((xcurrent%84)|0x80),0);
		//设定y坐标,(d%5)使Y轴坐标标定在83以内,有更好的健壮性;
        if(yaddr!=NULL)
	 lcd_write_byte(((yaddr%6)|0x40),0);
        else
          lcd_write_byte(((ycurrent%84)|0x80),0);
}

void lcd_clr()//清屏 
{ 
	char t,k;
        lcd_write_byte(HOR_ADDR,COM);
	for(t=0;t<6;t++) { 
                lcd_setadd(0,t);
		for(k=0;k<84;k++)  		
			lcd_write_byte(0X00,DATA); 
		 
	} 
} 

void setpix(char xpix,char ypix)
{
	moveto(xpix,ypix/8);
	lcd_write_byte(1<<(ypix%8),DATA);
}

void line(char xstart,char ystart,char xstop,char ystop)
{
	char xpix;
	if(xstart==xstop){
		moveto(xstart,ystart/8);
		lcd_write_byte(0xff<<((ystart-(ystart/8)*8)),DATA);
                //lcd_write_byte(0xff,DATA);
		moveto(xstart,ystop/8);
		lcd_write_byte((0xff>>((ystop/8+1)*8-ystop)),DATA);
                //lcd_write_byte(0xff,DATA);
		for(xpix=ystart/8+1;xpix<=ystop/8-1;xpix++){
			moveto(xstart,xpix);
			lcd_write_byte(0xff,DATA);	
		}
		
	}
	else{
		for(xpix=xstart;xpix<=xstop;xpix++){
			setpix(xpix,ystart);
		}
	}
}

void rectangle(char xstart,char ystart,char xstop,char ystop)
{
	line(xstart,ystart,xstop,ystart);
	line(xstart,ystart,xstart,ystop);
	//line(xstart+1,ystop-1,xstop,ystop-1);
        line(xstart+1,ystop-1,xstop-1,ystop);
	line(xstop,ystart,xstop,ystop); 
}

void lcd_write_str(const char *ch,char xstarto,char ystarto,char mod)
{
  	char *ach;
        //char const *ech=ch;
        char xstart,ystart;
	if(mod==HOR_ADDR){
                if(xstarto==NULL)xstart=xcurrent;
                  else xstart=xstarto;
                if(ystarto==NULL)ystart=ycurrent;
                   else ystart=ystarto;
                  // if((84-xstart)<6){
                    // ystart++;
                    // xstart=0;
                   //}
		//moveto(xstart/6*6,ystart);//保证每一个字符都有能在同一行显示
		for(;*ch;ch++){
                  if(ycurrent>5){
                    ycurrent=0;
                    return;
                  }
                  if(*ch=='\0'){
                    break;                  
                  }
                   if(*ch=='\n'){
                    ch++;
                    ystart++;
                    xstart=0;
                    
                    continue;
                  }
			ach=(char*)ASCII[(*ch)-0x20];
                        if((84-xstart)<6){
                             ystart++;
                             xstart=0;    //这种结构可能速度会比较慢,但却能保证每个字符能够完整显示
                           }
                       
                       moveto(xstart,ystart);
                       
			for(char i=0;i<=6;i++)   		
    				lcd_write_byte(ach[i],DATA);
                       xstart+=6;  
    		}
                //xcurrent=(xstart+length*6)%84;
                //ycurrent=(ystart+length/84);
                xcurrent=xstart;
                ycurrent=ystart;
	}
	
	else for(;*ch;ch++){
			moveto(xstart,ystart);
			ach=(char*)ASCII[(*ch)-0x20];
			for(char i=0;i<=6;i++){   		
    				lcd_write_byte(ach[i],DATA);
				ystart++;
			
			}
			if(!(ystart%6))xstart+=6;
    		}
  
}

	//写汉字 
void lcd_write_ch(const char *p,char xstarto,char ystarto,int mod) 
	//*p是数组字模，xstart是横向初始坐标x(0~84)，ystart纵向开始坐标x(0~5), 
	//length是字符点阵模式,mod由行和列组成,int共四位,高两位表示行,后两位表示列
{
        char row=0;
        //char width=0;
        int width=-1;
        //char i=0;
        int i=-1;
        char col=0;
        char xstart,ystart;
       
        
        switch(mod){
            case DOT_ARRAY_12:row=2;width=12;break;
            case DOT_ARRAY_16:row=2;width=16;break;
            case DOT_ARRAY_24:row=3;width=24;break;
            case DOT_ARRAY_OTHER:row=1;width=16;break;
            default:row=1;width=mod;break;
      
        
        }
        if(xstarto==NULL)xstart=xcurrent;
             else xstart=xstarto;
        if(ystarto==NULL)ystart=ycurrent;
             else ystart=ystarto;
             
        if((84-xstart)<width){
           ystart+=row;
           xstart=0;
        }  
        for(i=0;i<row;i++){
         for(col=0;col<width;col++){
            moveto(xstart+col,ystart+i);
            lcd_write_byte(p[i*width+col],DATA);
         }
        }
        xcurrent=(xstart+width)%84;
        if((xstart+width)>84)
          ycurrent=ystart+row;
        else
          ycurrent=ystart;
        moveto( xcurrent, ycurrent); 
        
} 

	//写汉字 
void lcd_write_chi(const char *p,char xstarto,char ystarto,int mod) 
	//*p是数组字模，xstart是横向初始坐标x(0~84)，ystart纵向开始坐标x(0~5), 
	//length是字符点阵模式,mod由行和列组成,int共四位,高两位表示行,后两位表示列
{
        char row=0;
        //char width=0;
        int width=-1;
        //char i=0;
        int i=-1;
        char col=0;
        char xstart,ystart;
       
        
        switch(mod){
            case DOT_ARRAY_12:row=2;width=12;break;
            case DOT_ARRAY_16:row=2;width=16;break;
            case DOT_ARRAY_24:row=3;width=24;break;
            case DOT_ARRAY_OTHER:row=1;width=16;break;
            default:row=1;width=mod;break;
      
        
        }
        if(xstarto==NULL)xstart=xcurrent;
             else xstart=xstarto;
        if(ystarto==NULL)ystart=ycurrent;
             else ystart=ystarto;
             
        if((84-xstart)<width){
           ystart+=row;
           xstart=0;
        }  
        for(i=0;i<row;i++){
         for(col=0;col<width;col++){
            moveto(xstart+col,ystart+i);
            lcd_write_byte(~p[i*width+col],DATA);
         }
        }
        xcurrent=(xstart+width)%84;
        if((xstart+width)>84)
          ycurrent=ystart+row;
        else
          ycurrent=ystart;
        moveto( xcurrent, ycurrent); 
        
} 

void invalidate(char xstart,char ystart,char xwidth,signed char yheight){
   char i;
   char col;
  for(i=0;i<yheight;i++)
         for(col=0;col<xwidth;col++){
            moveto(xstart+col,ystart+i);
            lcd_write_byte(0x00,DATA);
         }
}

void slider(char xstart,char ystart,char xstop,char height,int del){
  //(xstart,ystart):滚动条左上角坐标;(xstop,height):宽度和高度;del:滚动速度
  char i;
  char hei=0xff<<(8-height%9);
  char heii=(0x81<<(8-height%9))|0x80;
  
  lcd_write_byte(HOR_ADDR,COM);
   moveto(xstart,ystart);
   lcd_write_byte(hei,DATA);
   for(i=xstart+1;i<xstop;i++){
      lcd_write_byte(heii,DATA);
   }
   lcd_write_byte(hei,DATA);
   moveto(xstart,ystart);
    for(i=xstart+1;i<xstop+1;i++){
      lcd_write_byte(hei,DATA);
      delay(del);
   }
  
}


void menu(char xstart,char ystart, char **p,char length,char mod,char re){
    char** point=p;
    char i=0;
     //lcd_write_ch(*(point),xstart,ystart,mod);
    if(re==REVERSE_MODE)
             lcd_write_chi(*(point),xstart,ystart,mod);
          else
             lcd_write_ch(*(point),xstart,ystart,mod);
          
      while((++i)<length){
          if(re==REVERSE_MODE)
             lcd_write_chi(*(++point),NULL,NULL,mod);
          else
             lcd_write_ch(*(++point),NULL,NULL,mod);
      }
 }

/*void printf(const char *ch){
    lcd_write_str(ch,NULL,NULL,HOR_ADDR);
}*/ 

const char* int2string(int num)
{   
    char *buffer;
    
   
    while(num){
      *(buffer++)=((char)(num%10)+0x30);
      num/=10;
    }
    *(buffer)='\0';
    return (const char*)buffer;
}

void sliderv(void){
  rectangle(79,0,83,47);//画滚动条
  rectangle(80,8,82,14);     
}

char makechar(char row,char col){
  return (row<<5)|col;
}


void drawimage(const char* image,char xstart,char ystart,char width,char height){
      char x=xstart+width;
      char y=ystart+height;
      int i=-1;
      int m=-1;
      char xs;
      for(;ystart<y;ystart++){
        i++;
        m=-1;
        for(xs=xstart;xs<x;xs++){
          m++;
          moveto(xs,ystart);
          lcd_write_byte(image[i*width+m],DATA);
        }
      }

}

char isnum(char ch){
  if(ch>='0'&&ch<='9')
    return 1;
  else 
    return 0;
}

void lcd_write_num(long int num,char xstart,char ystart){
  if(num<0)
    num=0;
  do {
      drawimage(ASCII[num%10],xstart,ystart,6,1);
      xstart-=6;
  }while(num/=10);   
}

void printf(char *string,char num,char xstart,char ystart){
  int i=0;
  int n=0;
  /*char num=0;
  while((*zou)!='\0'){
    num++;
    zou++;
  }
  num/=2;*/
  for(i=0;i<num;i++)
    for(n=0;n<55;n++) {
      if(string[2*i]==haizi[n].name[0]&&string[2*i+1]==haizi[n].name[1]){
        drawimage(haizi[n].fontmod,xstart,ystart,12,2);
        xstart+=12;
        if(xstart==84){
          xstart=0;
          ystart+=2;
        }
        break;
      }
  }
      

}
  


#endif



















